package Implementacion;

import Entidades.Barco;
import Entidades.Orientacion;
import Entidades.Tablero;
import Implementaciones.Vector;
import Interfaces.BatallaNavalInterface;
import TDA.ConjuntoTDA;
import TDA.VectorTDA;
/**
 * 
 * @author Apolo I
 *
 */
public class BatallaNaval implements BatallaNavalInterface {

	/** O(n)
	 * 1 inicializa tablero
	 * 2 agrega los barcos al tablero
	 * 3 resuelve la ubicacion de los barcos
	 */
	public void resolverBatallaNaval(ConjuntoTDA<Barco> losBarcos, Tablero elTablero) {
		
		Vector<Barco> vBarcos = new Vector<Barco>();
		vBarcos.inicializarVector(elTablero.obtenerDimensionTablero());
		int i = 0;

		// Agrego los barcos
		while(!losBarcos.conjuntoVacio()){
			Barco unBarco = losBarcos.elegir();
			try {
				vBarcos.agregarElemento(i, unBarco);
			} catch (Exception e) {
				// aca no deberia entrar nunca
				e.printStackTrace();
			}
			i++;
			losBarcos.sacar(unBarco);
		}
		
		// Sin try. Que lo maneje UBarcos
		this.UbicarBarcos(vBarcos, 0, elTablero);		
	}
	
	/** O(n^3n)
	 * Ubica los barcos validando en cada etapa si la nueva ubicacion es valida
	 * @param barcos
	 * @param etapa
	 * @param tablero
	 * @return
	 */
	private boolean UbicarBarcos (VectorTDA<Barco> vBarcos, int etapa, Tablero elTablero){
		
		// primero valido si el tablero ya esta bien cubierto 
		// O(n4)
		if(vBarcos.capacidadVector() == etapa){
			if(elTablero.Validar()){ // O(n2)
				elTablero.imprimirTablero(); // O(n^2)
				return true;
			}
			return false;
		}
		else{
			// empiezo a tratar de poner posicion por posicion los barcos
			for(int fila = 0; fila < elTablero.obtenerDimensionTablero(); fila++){
				for(int col = 0; col < elTablero.obtenerDimensionTablero(); col++){
					try {
						Barco unBarco = vBarcos.recuperarElemento( etapa );
						if(unBarco.obtenerCantidadCeldas() == 1){
							
							// si es un barco de una sola posicion uso una sola orientacion
							unBarco.setearOrientacion(Orientacion.Horizontal); 
							
							// intento ponerlo en la posicion
							if(elTablero.setearBarco(fila, col, unBarco)){
								if(elTablero.validarPosiciones()){ 
									
									// si la posicion fue valida, intento poner el barco siguiente
									UbicarBarcos(vBarcos, etapa + 1, elTablero); 
									
								}
								// saco el barco tras la llamada recursiva, para probar otro camino solucion
								elTablero.quitarBarco(fila, col, unBarco);
							}
						}
						else{
							// para los barcos mas grandes pruebo las dos orientaciones
							for(Orientacion laOrientacion : Orientacion.values()){
								
								unBarco.setearOrientacion( laOrientacion );
								
								// pongo el barco en posicion y valido...
								if(elTablero.setearBarco(fila, col, unBarco)){
									if(elTablero.validarPosiciones()){
										UbicarBarcos(vBarcos, etapa + 1, elTablero);
									}
									elTablero.quitarBarco(fila, col, unBarco);
								}
							}
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
		return false;
	}
}
